#ifndef _SDB_BUFFERS_H_
#define _SDB_BUFFERS_H_

/* 
 * Spinneret - Semi-Structured Database Engine
 * Copyright (c) 2009 Tom Bradford <spinneretdb.org>
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a 
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 * DEALINGS IN THE SOFTWARE.
 */

/**
 * Buffer Manager manages Buffers (doh!).  This management includes pinning, 
 * locking, latching, on-demand reading, pre-fetching and write flushing.
 */

#include "main/common.h"
#include "utils/mem.h"
#include "buffers/pager.h"

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
    
    
/** Incomplete type for Buffer Manager instances */
typedef struct sdb_buffers_t sdb_buffers_t;

/** Incomplete type for Buffer instances */
typedef struct sdb_buffer_t sdb_buffer_t;

/** Create a Buffer Manager instance */
sdb_buffers_t* sdb_buffers_new(sdb_mem_t* mem);

/** Initialize a Buffer Manager instance */
sdb_buffers_t* sdb_buffers_init(sdb_buffers_t* bufmgr, sdb_pager_t* pager);

/** Create a Buffer instance */
sdb_buffer_t* sdb_buffer_new(sdb_mem_t* mem);

/** Initialize a Buffer instance */
sdb_buffer_t* sdb_buffer_init(sdb_buffer_t*, sdb_size_t len);

/** Returns the number of bytes available for read/writing */
sdb_size_t sdb_buffer_avail(sdb_buffer_t* buffer);

/** Skip ahead the specified number of bytes from the present position */
sdb_size_t sdb_buffer_skip(sdb_buffer_t* buffer, sdb_size_t len);

/** Copy the contents of data into the buffer at its present position */
sdb_size_t sdb_buffer_put(sdb_buffer_t* buffer, void* data, sdb_size_t len);

/** Copy the contents of the buffer into data from its present position */
sdb_size_t sdb_buffer_get(sdb_buffer_t* buffer, void* data, sdb_size_t len);

/** Copy the contents of the buffer into the target buffer */
sdb_size_t sdb_buffer_copy(sdb_buffer_t* buffer, sdb_buffer_t* target);

/** Bookmark the present buffer position for a later reset using popMark */
void sdb_buffer_pushMark(sdb_buffer_t* buffer);

/** Returns the buffer position to the most recently set bookmark */
void sdb_buffer_popMark(sdb_buffer_t* buffer);

/** Rewinds the present position to the beginning of the buffer */
void sdb_buffer_rewind(sdb_buffer_t* buffer);

/** Buffer flip, setting limit to the current position, and position to zero */
void sdb_buffer_flip(sdb_buffer_t* buffer);

/** Returns a pointer to the internal data of the buffer */
void* sdb_buffer_data(sdb_buffer_t* buffer);

/** Returns a point to the current position of the buffer */
void* sdb_buffer_pos(sdb_buffer_t* buffer);

/** Returns the length of the buffer (in bytes) */
sdb_size_t sdb_buffer_len(sdb_buffer_t* buffer);

/** Returns the limit of the buffer (in bytes) */
sdb_size_t sdb_buffer_limit(sdb_buffer_t* buffer);

    
#ifdef __cplusplus
}
#endif // __cplusplus

#endif // _SDB_BUFFERS_H_
